﻿using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.AnalysisServices.AdomdClient;

namespace Galaktika.BI.Silverlight.ClientApp.Web.Runtime.DataAccess
{
    public static class OlapConnectionPool
    {
        private static Dictionary<string, AdomdConnection> m_Pool;

        private static bool m_IsInitialized;
        public static bool IsInitialized
        {
            get
            {
                return m_IsInitialized;
            }
        }

        public static CellSet ExecutePooledQuery(string connectionString, string query)
        {
            if (!m_IsInitialized)
            {
                throw new InvalidOperationException("Olap thread pool is not initialized.");
            }

            int tryNumber = 0;
            CellSet cs = null;
        RETRY_LABEL:
            try
            {
                tryNumber++;
                using (AdomdCommand cmd = new AdomdCommand(query, GetConnection(connectionString)))
                {
                    //if (cmd.Connection.State != System.Data.ConnectionState.Open)
                    //{
                    //    cmd.Connection.Open();
                    //}
                    cs = cmd.ExecuteCellSet();
                }
            }
            catch (AdomdCacheExpiredException)
            {
                if (tryNumber > 1)
                {
                    throw;
                }
                else
                {
                    goto RETRY_LABEL;
                }
            }

            return cs;
        }

        public static AdomdConnection GetConnection(string connectionString)
        {
            AdomdConnection conn;
            lock (m_Pool)
            {
                m_Pool.TryGetValue(connectionString, out conn);
                if (conn == null)
                {
                    conn = CreateConnection(connectionString);
                }
            }

            return conn;
        }

        public static bool IsPooled(AdomdConnection conn)
        {
            if (m_IsInitialized)
            {
                return m_Pool.ContainsValue(conn);
            }

            return false;
        }

        private static AdomdConnection CreateConnection(string connectionString)
        {
            AdomdConnection conn = new AdomdConnection(connectionString);
            conn.Open();
            m_Pool.Add(connectionString, conn);

            return conn;
        }

        public static void Initialize()
        {
            if (m_IsInitialized)
            {
                throw new InvalidOperationException();
            }

            m_IsInitialized = true;
            m_Pool = new Dictionary<string, AdomdConnection>();
        }

        public static void Dispose()
        {
            if (m_IsInitialized)
            {
                foreach (AdomdConnection conn in m_Pool.Values)
                {
                    conn.Close();
                    conn.Dispose();
                }
                m_Pool = null;
                m_IsInitialized = false;
            }
        }
    }
}
